package org.yagnus.stats.samplers;

/**
 * 
 * @author hc.busy
 * 
 *         This class containing things shared by all samplers implemented here.
 *         Derived abstract subclasses should set policies on if further derived
 *         classes should use the shared RNG or a separate one or a separate one
 *         each time.
 * 
 */
public abstract class Sampler {

	private static final ThreadLocal<RandomNumberGeneratorShuffle> _rng = new ThreadLocal<RandomNumberGeneratorShuffle>() {

		@Override
		final protected RandomNumberGeneratorShuffle initialValue() {
			return new UnsynchronizedJavaRandom();
			// alternatively return new JavaUtilRandom();
		}
	};
	private RandomNumberGeneratorShuffle _my_rng = null;

	/**
	 * all methods in this and derived classes should call this function to
	 * obtain the source of entropy
	 * 
	 * @return
	 */
	public final RandomNumberGeneratorShuffle rng() {
		if (_my_rng == null) {
			return _rng.get();
		} else {
			return _my_rng;
		}
	}

	public Sampler(UnsynchronizedJavaRandom r) {
		_my_rng = r;
	}

	public Sampler() {
		_my_rng = null;
	}

	/**
	 * Specify a source of entropy
	 * 
	 * @param r
	 */
	public final void setRng(UnsynchronizedJavaRandom r) {
		_my_rng = r;
	}

	/**
	 * Seed, if possible the source of entropy
	 * 
	 * @param seed
	 * @return true if the Random class was reseeded.
	 */
	public final boolean reseed(int seed) {
		if (_my_rng != null) {
			_my_rng.setSeed(seed);
			return true;
		}
		return false;
	}

	/**
	 * Set the seed for the thread local randomizer.
	 * 
	 * @param seed
	 * @return
	 */
	public static boolean reseedThreadLocalRng(int seed) {
		_rng.get().setSeed(seed);
		return true;
	}
}
